﻿/***************************************************************
* File    : ChartingQueue.cs
* Author  : Kyle Burgess
*
* Description:
*   Handles a Queue data structure that is ultimately used to plot the live charts
*
* History :
***************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RLGDashboard
{
    class ChartingQueue
    {
        // Private attribues
        // Variables that can be used to constantly track the head and tail of the linked list
        private QueueNode head;
        private QueueNode tail;

        // Used to track the number of items active in the queue
        private int queueCount;

        //We need 60 seconds worth of data
        private int queueTimeLength = 60;

        //Number of data points per second
        private int frequency = 8;

        //Represents the number of active items we can save in the list
        private int maxQueueLength;

        /***************************************************************
        * Public                 ChartingQueue
        *
        * ChartingQueue function to instantiate a ChartingQueue
        *
        * Inputs
        * None
        * 
        * Outputs
        * None
        * 
        * History:
        ****************************************************************/
        public ChartingQueue()
        {
            //Initialize head and tail
            head = null;
            tail = null;

            //Initialize count to 0
            queueCount = 0;
            
            //Calculate the maximum number of elements we can have in our queue (count doesn't start at 0, so plus 1).
            maxQueueLength = (queueTimeLength * frequency) + 1;
        }

        /***************************************************************
        * Public                 addNode
        *
        * ChartingQueue function to add a node to the queue.
        *
        * Inputs
        * object value: The sensor value which needs to be added to teh queue
        * 
        * Outputs
        * None
        * 
        * History:
        ****************************************************************/
        public void addNode(object value)
        {
            //If we are adding an item to our existing list (most common)
            if (head != null)
            {
                //Create a new node with the new value
                QueueNode newNode = new QueueNode(value);

                //Set the new node's previous pointer to our former tail.
                newNode.previousNode = tail;

                //Set the former tail to point to the new node
                tail.nextNode = newNode;

                //The newNode is now the last element in the list.
                tail = newNode;
            }
            else //This is the first item in our list (least common)
            {
                //The head of our queue will be the newly created node.
                head = new QueueNode(value);

                //There is no previous or next node
                head.previousNode = null;
                head.nextNode = null;

                //Right now the tail will be the head of the queue
                tail = head;
            }

            //Increment the number of items in our queue.
            queueCount++;

            //If adding this new item causes us to go over the 
            if (queueCount == maxQueueLength)
            {
                //Read the first item off of the queue by making the head point to the next item in the queue.
                head = head.nextNode;

                //Release the pointer to the previous Node, this allows Garbage Collection to clean it up eventually.
                head.previousNode = null;

                //We have read an item off of our queue
                queueCount--;
            }
        }

        /***************************************************************
        * Public                 DrawPoints
        *
        * ChartingQueue function to add a node to the queue.
        *
        * Inputs
        * System.Windows.Forms.DataVisualization.Charting.Chart chart: a handle to the chart that we will plot on.
        * 
        * string seriesName: The string name of the series that we are going to plot for.
        * 
        * Outputs
        * None
        * 
        * History:
        ****************************************************************/
        public void DrawPoints(System.Windows.Forms.DataVisualization.Charting.Chart chart, string seriesName)
        {
            // Create a QueueNode that will be used to iterate through the list.
            QueueNode current = head;

            //Start at the end of the queue (the head of the queue), and iterate backwards
            for (int index = queueCount - 1; index >= 0; index--)
            {
                //Pull the current node's sensor value
                object value = current.nodeValue;

                //Increment the current node to the next node
                current = current.nextNode;

                //Based on the index we're at, calculate a time.  (ex: point 480 becomes time -60)
                double time = (double)(-index);
                time = (time / frequency);

                //If the sensor value is not an ERROR
                if (value.ToString() != "")
                {
                    //Plot the sensor value against time.
                    chart.Series[seriesName].Points.AddXY(time, value);
                }
            }
        }

        //Construct tiny class to handle the attributes of a node
        private  class QueueNode
        {
            //Point to the previous and next nodes in the list
            public QueueNode previousNode;
            public QueueNode nextNode;

            //Hold the current sensor value
            public object nodeValue;

            //Create a new node.
            public QueueNode(object value)
            {
                nodeValue = value;
            }
        }
    }
}
